using Microsoft.EntityFrameworkCore;
using RAG.Domain.Entities.App;

namespace RAG.Infrastructure.Data;

public class RagDbContext : DbContext
{
    public RagDbContext(DbContextOptions<RagDbContext> options) : base(options)
    {
    }

    // DbSet 配置
    public DbSet<Users> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<Permission> Permissions { get; set; }
    public DbSet<Session> Sessions { get; set; }
    public DbSet<Conversation> Conversations { get; set; }
    public DbSet<KnowledgeBase> KnowledgeBases { get; set; }
    public DbSet<Document> Documents { get; set; }
    public DbSet<DocumentChunk> DocumentChunks { get; set; }
    public DbSet<Vector> Vectors { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        // 配置表名和字段命名规则（下划线）
        ConfigureUsers(modelBuilder);
        ConfigureDocument(modelBuilder);
        ConfigureDocumentChunk(modelBuilder);
        ConfigureKnowledgeBase(modelBuilder);
        ConfigureConversation(modelBuilder);
        ConfigureSession(modelBuilder);
        ConfigureVector(modelBuilder);
        ConfigureRole(modelBuilder);
        ConfigurePermission(modelBuilder);
    }

    private void ConfigureUsers(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Users>(entity =>
        {
            entity.ToTable("users");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.Username).HasColumnName("username").HasMaxLength(50).IsRequired();
            entity.Property(e => e.Password).HasColumnName("password").HasMaxLength(255).IsRequired();
            entity.Property(e => e.Salt).HasColumnName("salt").HasMaxLength(60).IsRequired();
            entity.Property(e => e.Email).HasColumnName("email").HasMaxLength(100).IsRequired();
            entity.Property(e => e.Phone).HasColumnName("phone").HasMaxLength(20).IsRequired();
            entity.Property(e => e.Avatar).HasColumnName("avatar").HasMaxLength(500);
            entity.Property(e => e.AccountStatus).HasColumnName("account_status").HasDefaultValue(0);
            entity.Property(e => e.FailedLoginAttempts).HasColumnName("failed_login_attempts").HasDefaultValue(0);
            entity.Property(e => e.LockedUntil).HasColumnName("locked_until");
            entity.Property(e => e.LastFailedLogin).HasColumnName("last_failed_login");
            entity.Property(e => e.LastActivityTime).HasColumnName("last_activity_time");
            entity.Property(e => e.LastLoginTime).HasColumnName("last_login_time");
            entity.Property(e => e.IsActive).HasColumnName("is_active").HasDefaultValue(true);
            entity.Property(e => e.IsDeleted).HasColumnName("is_deleted").HasDefaultValue(false);
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 索引
            entity.HasIndex(e => e.Username).IsUnique();
            entity.HasIndex(e => e.Email).IsUnique();
            // 移除Phone的唯一索引，因为手机号可能为空
            entity.HasIndex(e => e.Phone);
        });
    }

    private void ConfigureDocument(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Document>(entity =>
        {
            entity.ToTable("documents");
            entity.HasKey(e => e.DocumentId);
            
            entity.Property(e => e.DocumentId).HasColumnName("document_id");
            entity.Property(e => e.DocumentTitle).HasColumnName("document_title").HasMaxLength(200).IsRequired();
            entity.Property(e => e.DocumentFileName).HasColumnName("document_file_name").HasMaxLength(255).IsRequired();
            entity.Property(e => e.DocumentFilePath).HasColumnName("document_file_path").HasMaxLength(500).IsRequired();
            entity.Property(e => e.DocumentFileType).HasColumnName("document_file_type").HasMaxLength(50).IsRequired();
            entity.Property(e => e.DocumentFileSize).HasColumnName("document_file_size");
            entity.Property(e => e.DocumentStatus).HasColumnName("document_status").HasMaxLength(50).IsRequired();
            entity.Property(e => e.UserId).HasColumnName("user_id");
            entity.Property(e => e.KnowledgeBaseId).HasColumnName("knowledge_base_id");
            entity.Property(e => e.DocumentAccessLevel).HasColumnName("document_access_level").HasMaxLength(50).IsRequired();
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.User)
                .WithMany(e => e.Documents)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.KnowledgeBase)
                .WithMany(e => e.Documents)
                .HasForeignKey(e => e.KnowledgeBaseId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.UserId);
            entity.HasIndex(e => e.KnowledgeBaseId);
            entity.HasIndex(e => e.DocumentStatus);
        });
    }

    private void ConfigureDocumentChunk(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<DocumentChunk>(entity =>
        {
            entity.ToTable("document_chunks");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.DocumentId).HasColumnName("document_id");
            entity.Property(e => e.ChunkIndex).HasColumnName("chunk_index");
            entity.Property(e => e.DocumentChunkContent).HasColumnName("content").HasColumnType("text").IsRequired();
            entity.Property(e => e.TokenCount).HasColumnName("token_count");
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.Document)
                .WithMany(e => e.DocumentChunks)
                .HasForeignKey(e => e.DocumentId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.DocumentId);
            entity.HasIndex(e => e.ChunkIndex);
        });
    }

    private void ConfigureKnowledgeBase(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<KnowledgeBase>(entity =>
        {
            entity.ToTable("knowledge_bases");
            entity.HasKey(e => e.KnowledgeBaseId);
            
            entity.Property(e => e.KnowledgeBaseId).HasColumnName("knowledge_base_id");
            entity.Property(e => e.KnowledgeBaseName).HasColumnName("knowledge_base_name").HasMaxLength(100).IsRequired();
            entity.Property(e => e.KnowledgeBaseDescription).HasColumnName("knowledge_base_description").HasMaxLength(500);
            entity.Property(e => e.UserId).HasColumnName("user_id");
            entity.Property(e => e.IsPublic).HasColumnName("is_public").HasDefaultValue(false);
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.User)
                .WithMany(e => e.KnowledgeBases)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.UserId);
            entity.HasIndex(e => e.IsPublic);
        });
    }

    private void ConfigureConversation(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Conversation>(entity =>
        {
            entity.ToTable("conversations");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.SessionId).HasColumnName("session_id");
            entity.Property(e => e.UserId).HasColumnName("user_id");
            entity.Property(e => e.ConversationQuestion).HasColumnName("conversation_question").HasColumnType("text").IsRequired();
            entity.Property(e => e.ConversationAnswer).HasColumnName("conversation_answer").HasColumnType("text").IsRequired();
            entity.Property(e => e.SourceChunks).HasColumnName("conversation_source_chunks").HasColumnType("jsonb");
            entity.Property(e => e.ConversationModel).HasColumnName("conversation_model").HasMaxLength(100).IsRequired();
            entity.Property(e => e.PromptTokens).HasColumnName("prompt_tokens");
            entity.Property(e => e.CompletionTokens).HasColumnName("completion_tokens");
            entity.Property(e => e.LatencyMs).HasColumnName("latency_ms");
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.Session)
                .WithMany(e => e.Conversations)
                .HasForeignKey(e => e.SessionId)
                .OnDelete(DeleteBehavior.Cascade);

            entity.HasOne(e => e.User)
                .WithMany(e => e.Conversations)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.SessionId);
            entity.HasIndex(e => e.UserId);
            entity.HasIndex(e => e.CreatedAt);
        });
    }

    private void ConfigureSession(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Session>(entity =>
        {
            entity.ToTable("sessions");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.UserId).HasColumnName("user_id");
            entity.Property(e => e.SessionTitle).HasColumnName("session_title").HasMaxLength(200).IsRequired();
            entity.Property(e => e.SessionStatus).HasColumnName("session_status").HasMaxLength(50).IsRequired();
            entity.Property(e => e.LastActiveAt).HasColumnName("last_active_at");
            entity.Property(e => e.Metadata).HasColumnName("metadata").HasColumnType("jsonb");
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.User)
                .WithMany(e => e.Sessions)
                .HasForeignKey(e => e.UserId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.UserId);
            entity.HasIndex(e => e.SessionStatus);
            entity.HasIndex(e => e.LastActiveAt);
        });
    }

    private void ConfigureVector(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Vector>(entity =>
        {
            entity.ToTable("vectors");
            entity.HasKey(e => e.VectorId);
            
            entity.Property(e => e.VectorId).HasColumnName("vector_id");
            entity.Property(e => e.DocumentChunkId).HasColumnName("document_chunk_id");
            entity.Property(e => e.Embedding).HasColumnName("embedding").HasColumnType("real[]").IsRequired();
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 外键关系
            entity.HasOne(e => e.DocumentChunk)
                .WithOne(e => e.Vector)
                .HasForeignKey<Vector>(e => e.DocumentChunkId)
                .OnDelete(DeleteBehavior.Cascade);

            // 索引
            entity.HasIndex(e => e.DocumentChunkId);
        });
    }

    private void ConfigureRole(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Role>(entity =>
        {
            entity.ToTable("roles");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.RoleName).HasColumnName("role_name").HasMaxLength(50).IsRequired();
            entity.Property(e => e.RoleDescription).HasColumnName("role_description").HasMaxLength(200);
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 索引
            entity.HasIndex(e => e.RoleName).IsUnique();
        });

        // 配置Users和Role的多对多关系
        modelBuilder.Entity<Users>()
            .HasMany(u => u.Roles)
            .WithMany(r => r.Users)
            .UsingEntity(
                "user_roles",
                l => l.HasOne(typeof(Role)).WithMany().HasForeignKey("RolesId").HasPrincipalKey("Id"),
                r => r.HasOne(typeof(Users)).WithMany().HasForeignKey("UsersId").HasPrincipalKey("Id"));
    }

    private void ConfigurePermission(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Permission>(entity =>
        {
            entity.ToTable("permissions");
            entity.HasKey(e => e.Id);
            
            entity.Property(e => e.Id).HasColumnName("id");
            entity.Property(e => e.PermissionCode).HasColumnName("permission_code").HasMaxLength(100).IsRequired();
            entity.Property(e => e.PermissionName).HasColumnName("permission_name").HasMaxLength(100).IsRequired();
            entity.Property(e => e.PermissionDescription).HasColumnName("permission_description").HasMaxLength(200);
            entity.Property(e => e.CreatedAt).HasColumnName("created_at");
            entity.Property(e => e.UpdatedAt).HasColumnName("updated_at");

            // 索引
            entity.HasIndex(e => e.PermissionCode).IsUnique();
        });

        // 配置Role和Permission的多对多关系
        modelBuilder.Entity<Role>()
            .HasMany(r => r.Permissions)
            .WithMany(p => p.Roles)
            .UsingEntity(
                "role_permissions",
                l => l.HasOne(typeof(Permission)).WithMany().HasForeignKey("PermissionsId").HasPrincipalKey("Id"),
                r => r.HasOne(typeof(Role)).WithMany().HasForeignKey("RolesId").HasPrincipalKey("Id"));
    }
}
